//@author A0096723X
///@class EntriesManager
#include "EntriesManager.h"

const char* EntriesManager::OUTPUT_MSG_IS_EMPTY="%s is empty"; 
const char* EntriesManager::OUTPUT_MSG_INVALID="%s is invalid";
const char* EntriesManager::OUTPUT_MSG_CONFLICT="%s has conflicts!";
const char* EntriesManager::OUTPUT_MSG_SUCCESS_ADD="%s was added";
const char* EntriesManager::OUTPUT_MSG_SUCCESS_DELETE="%s was deleted";
const char* EntriesManager::OUTPUT_MSG_SUCCESS_DISPLAY="%s was displayed";
const char* EntriesManager::OUTPUT_MSG_SUCCESS_EDIT="%s was edited";
const char* EntriesManager::OUTPUT_MSG_SUCCESS_CLEAR="%s was Cleared";
const char* EntriesManager::OUTPUT_MSG_SUCCESS_SEARCH="%s was searched"; 
const char* EntriesManager::OUTPUT_MSG_SUCCESS_UNDO="%s was undone"; 
const char* EntriesManager::OUTPUT_MSG_SUCCESS_REDO="%s was redone"; 
const char* EntriesManager::OUTPUT_MSG_SUCCESS_COMPLETED="%s was completed"; 
const char* EntriesManager::OUTPUT_MSG_SEARCH_NO_ITEMS= "No items that fufil search criteria: %s";

const string EntriesManager::_fileName= "storage.txt";
const string EntriesManager::STRING_NULL = "";
const string EntriesManager::ENTRY_TYPE_TASK = "TASK";
const string EntriesManager::ENTRY_TYPE_EVENT = "EVENT";
const string EntriesManager::OUTPUT_MSG_DEFAULT_VIEW = "Default view";
const string EntriesManager::OUTPUT_MSG_ALL = "All";
const string EntriesManager::OUTPUT_MSG_UNDO_STACK = "Undo Stack";
const string EntriesManager::OUTPUT_MSG_REDO_STACK = "Redo Stack";
const string EntriesManager::OUTPUT_MSG_LAST_COMMAND = "Last command";
const string EntriesManager::OUTPUT_MSG_COMPLETE = "Complete";
const string EntriesManager::OUTPUT_MSG_INCOMPLETE = "Incomplete";
const string EntriesManager::OUTPUT_MSG_ENTRIES = " Entries";
const string EntriesManager::OUTPUT_MSG_ITEMS_IN = "Items in ";
const string EntriesManager::OUTPUT_MSG_ITEMS_UPCOMING_WEEK = "Items for upcoming week";

const QString EntriesManager::LOG_ADD_COMMAND = "add command\n";
const QString EntriesManager::LOG_DELETE_COMMAND = "delete command\n";
const QString EntriesManager::LOG_EDIT_COMMAND = "edit command\n";
const QString EntriesManager::LOG_UNDO_COMMAND = "undo command\n";
const QString EntriesManager::LOG_REDO_COMMAND = "redo command\n";
const QString EntriesManager::LOG_CLEAR_COMMAND = "clear command\n";
const QString EntriesManager::LOG_SET_DONE_COMMAND = "set done command\n";
const QString EntriesManager::LOG_SEARCH_COMMAND  = "search command\n";
const QString EntriesManager::LOG_SEARCH_TASK_COMMAND = "search tasks\n";
const QString EntriesManager::LOG_SEARCH_EVENT_COMMAND = "search events\n";
const QString EntriesManager::LOG_SEARCH_WEEK_COMMAND = "search week\n";
const QString EntriesManager::LOG_SEARCH_DAY_COMMAND = "search day\n";
const QString EntriesManager::LOG_SEARCH_STATUS_COMMAND = "search status\n";

// Following functions are publicly accessible, supplemented by helper functions.
//Mainly to be accessed by logic(BOT) component
EntriesManager& EntriesManager::getInstance(FileManager* file) {
	static EntriesManager instance(*file);
	return instance;
}
EntriesManager& EntriesManager::getInstance() {
	static EntriesManager instance;
	return instance;
}
CommonEnum::ReturnStatus EntriesManager::addCommand(Entry* newEntry) {
	assert(newEntry != NULL);
	qxtLog->info(QList<QVariant>() << LOG_ADD_COMMAND);
	
	generateNewVector();
	string messageDisplayed = addToEntries(newEntry);
	if(_entries.conflictVector.size()>0)
		return sendOutputMessage(messageDisplayed, MSG_CONFLICT);
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_ADD); 
}
CommonEnum::ReturnStatus EntriesManager::deleteCommand(int index) {
	qxtLog->info(QList<QVariant>() <<LOG_DELETE_COMMAND);

	validateIndex(index);
	generateNewVector();
	string messageDisplayed = removeFromEntries(index);
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_DELETE);  
}
CommonEnum::ReturnStatus EntriesManager::displayCommand(DISPLAY_TYPE type) {
	switch(type){
	case DISPLAY_TYPE_ALL:
		showAll();
		break;
	case DISPLAY_TYPE_DEFAULT:
		resetView();
		break;
	default:
		assert(false);
	}
	string messageDisplayed = OUTPUT_MSG_DEFAULT_VIEW;
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_DISPLAY); 
}
CommonEnum::ReturnStatus EntriesManager::displayCommand() {
	return displayCommand(DISPLAY_TYPE_DEFAULT);
}
CommonEnum::ReturnStatus EntriesManager::displayAllCommand() {
	return displayCommand(DISPLAY_TYPE_ALL);
}
CommonEnum::ReturnStatus EntriesManager::editCommand(int index, vector<string> entryVector) {
	qxtLog->info(QList<QVariant>() << LOG_EDIT_COMMAND);

	validateIndex(index);
	generateNewVector();
	assert(entryVector.size()==5);
	string messageDisplayed =  editEntry(index, entryVector);
	if(_entries.conflictVector.size()>0) {
		return sendOutputMessage(messageDisplayed, MSG_CONFLICT);
	}
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_EDIT); 
}
CommonEnum::ReturnStatus EntriesManager::undoCommand() {// delete the current vector, take old vector, update
	qxtLog->info(QList<QVariant>() << LOG_UNDO_COMMAND);

	checkUndoStack();
	string messageDisplayed = revertLastState();
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_UNDO); 
}
CommonEnum::ReturnStatus EntriesManager::redoCommand() {// delete the current vector, take old vector, update
	qxtLog->info(QList<QVariant>() << LOG_REDO_COMMAND);

	checkRedoStack();
	string messageDisplayed = revertRedoState();
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_REDO); 
}
CommonEnum::ReturnStatus EntriesManager::clearCommand() {
	qxtLog->info(QList<QVariant>() << LOG_CLEAR_COMMAND);

	generateNewVector();
	string messageDisplayed = clearEntries();
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_CLEAR); 
}
CommonEnum::ReturnStatus EntriesManager::setDoneCommand(int index) {
	qxtLog->info(QList<QVariant>() << LOG_SET_DONE_COMMAND);

	validateIndex(index);
	generateNewVector();

	string messageDisplayed = setEntryDone(index);
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_COMPLETED); 
}
CommonEnum::ReturnStatus EntriesManager::searchCommand(string target, CommonEnum::SEARCH_TYPE searchType) {
	qxtLog->info(QList<QVariant>() << LOG_SEARCH_COMMAND);

	string messageDisplayed = searchEntries(target, searchType);
	if(currentDisplayIsEmpty()){
		return sendOutputMessage(messageDisplayed, MSG_SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_SEARCH);
}
CommonEnum::ReturnStatus EntriesManager::searchCommand(string target) {
	return searchCommand(target, CommonEnum::SEARCH_TYPE_CUMULATIVE);
}
CommonEnum::ReturnStatus EntriesManager::searchTasks() {
	qxtLog->info(QList<QVariant>() << LOG_SEARCH_TASK_COMMAND);

	string messageDisplayed = searchEntriesTasks();
	if(currentDisplayIsEmpty()){
		return sendOutputMessage(messageDisplayed, MSG_SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_SEARCH); 
}
CommonEnum::ReturnStatus EntriesManager::searchEvents() {
	qxtLog->info(QList<QVariant>() << LOG_SEARCH_EVENT_COMMAND);

	string messageDisplayed = searchEntriesEvents();
	if(currentDisplayIsEmpty()){
		return sendOutputMessage(messageDisplayed, MSG_SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_SEARCH); 
}
CommonEnum::ReturnStatus EntriesManager::searchDay(QDate target, CommonEnum::SEARCH_TYPE searchType) {
	qxtLog->info(QList<QVariant>() << LOG_SEARCH_DAY_COMMAND);

	string messageDisplayed = searchEntriesDay(target, searchType);
	if(currentDisplayIsEmpty()){
		return sendOutputMessage(messageDisplayed, MSG_SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_SEARCH); 
}
CommonEnum::ReturnStatus EntriesManager::searchDay(QDate target) {
	return searchDay(target, CommonEnum::SEARCH_TYPE_DEFAULT);
}
CommonEnum::ReturnStatus EntriesManager::searchDayBefore(QDate target) {
	return searchDay(target, CommonEnum::SEARCH_TYPE_CUMULATIVE);
}
CommonEnum::ReturnStatus EntriesManager::searchDayPastNotDone(QDate target) {
	resetView();
	return searchDay(target, CommonEnum::SEARCH_TYPE_CUMULATIVE);
}
CommonEnum::ReturnStatus EntriesManager::searchWeek() {
	QDate target = QDate::currentDate().addDays(7);
	CommonEnum::ReturnStatus output = searchDay(target, CommonEnum::SEARCH_TYPE_CUMULATIVE); 
	output.displayMsg[0][0].entry.first = OUTPUT_MSG_ITEMS_UPCOMING_WEEK;
	return output;
}
CommonEnum::ReturnStatus EntriesManager::searchStatus(bool target) {
	qxtLog->info(QList<QVariant>() << LOG_SEARCH_STATUS_COMMAND);

	string messageDisplayed = searchEntriesStatus(target);
	if(currentDisplayIsEmpty()){
		return sendOutputMessage(messageDisplayed, MSG_SEARCH_NO_ITEMS);
	}
	return sendOutputMessage(messageDisplayed, MSG_SUCCESS_SEARCH); 
}
CommonEnum::ReturnStatus EntriesManager::searchStatus() {
	return searchStatus(false);
}

CommonEnum::ReturnCount EntriesManager::getCount(){
	return EntriesSorter::getCount(getAllEntries());
}

vector<Entry*> EntriesManager::getActive() {
	return _entries.activeEntries;
}

QStringList EntriesManager::getNameVect() {
	QStringList output;
	vector<Entry*> allEntries = getAllEntries();
	for(int i=0; i<allEntries.size(); i++)
		output << QString::fromStdString(allEntries[i]->getName());
	return output;
}




//private functions below

EntriesManager::EntriesManager(FileManager& file): _file(file)
{
	initEntries();
}
EntriesManager::EntriesManager(): _file(FileManager::getInstance(_fileName)){
	initEntries();
}
EntriesManager::~EntriesManager(void) {
	deleteVector(_entries.activeEntries);
	deleteVector(_entries.inactiveEntries);
	clearStack(_entriesHist);
	clearStack(_entriesRedo);
}

//Helper functions below to supplement the public functions above.

//Handles the return values for the main public functions
CommonEnum::ReturnStatus EntriesManager::sendOutputMessage(string messageDisplayed, MSG_TYPE cmd) {
	char buffer[99999];
	CommonEnum::ReturnStatus output;

	switch (cmd){
		case MSG_IS_EMPTY:
			sprintf_s(buffer, OUTPUT_MSG_IS_EMPTY, messageDisplayed.c_str());
			break;
		case MSG_INVALID:// failure in undo, edit and delete function
			sprintf_s(buffer, OUTPUT_MSG_INVALID, messageDisplayed.c_str());
			break;
		case MSG_CONFLICT:
			sprintf_s(buffer, OUTPUT_MSG_CONFLICT, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_ADD:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_ADD, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_DISPLAY:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_DISPLAY, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_SEARCH:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_SEARCH, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_DELETE:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_DELETE, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_EDIT:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_EDIT, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_UNDO:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_UNDO, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_REDO:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_REDO, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_CLEAR:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_CLEAR, messageDisplayed.c_str());
			break;
		case MSG_SUCCESS_COMPLETED:
			sprintf_s(buffer, OUTPUT_MSG_SUCCESS_COMPLETED, messageDisplayed.c_str());
			break;
		case MSG_SEARCH_NO_ITEMS:
			sprintf_s(buffer, OUTPUT_MSG_SEARCH_NO_ITEMS, messageDisplayed.c_str());
			break;
	}
	output.statusMsg=buffer;
	output.displayMsg=printVectorToString();
	return output;
}

//merges the active and inactive vector of current state and returns the vector
vector<Entry*> EntriesManager::getAllEntries() {//merges the active and inactive entries
	vector<Entry*> tempVector;
	tempVector.insert(tempVector.end(), _entries.activeEntries.begin(),_entries.activeEntries.end());
	tempVector.insert(tempVector.end(),_entries.inactiveEntries.begin(), _entries.inactiveEntries.end());
	return tempVector;
}
//takes in a entry pointer and filters out the entries that conflict.
//returns vector of Entry* that conflict.
vector<Entry*> EntriesManager::getConflict(Entry* newEntry) {
	vector<Entry*> temp = (getAllEntries());
	vector<Entry*> found;
	vector<Entry*> notFound;
	for(int i=0; i<temp.size(); i++) {
		if(temp[i]->isConflict(newEntry) && temp[i]!=newEntry && !temp[i]->getStatus()) {//DEPENDENCY ON EVENTS
			found.push_back(temp[i]);//newEntry itself not included
		} else {
			notFound.push_back(temp[i]);
		}
	}
	return found;
}
//Prints the current activeEntries to the output format
vector<vector<CommonEnum::ReturnString>> EntriesManager::printVectorToString() {
	CommonEnum::ReturnStatus output;
	switch(_entries.currentDisplayFormat) {
	case DISPLAY_DEFAULT:
	default:
		EntriesSorter::defaultSort(_entries.activeEntries);
		output.displayMsg = getDefaultString();//printVectorToString(_entries.activeEntries);
		break;
	case DISPLAY_SEARCH:
		EntriesSorter::sortByDate(_entries.activeEntries);
		output.displayMsg = getSearchString();
		break;
	case DISPLAY_SEARCH_DATE:
		EntriesSorter::sortByDate(_entries.activeEntries);
		output.displayMsg = getSearchDateString();
		break;
	}
	return output.displayMsg;
}

//Functions below used for display 
vector<vector<CommonEnum::ReturnString>> EntriesManager::getDefaultString() {
	EntriesDisplay display(_entries.newEntry, _entries.conflictVector);
	return display.getDefaultString(_entries.activeEntries);
}
vector<vector<CommonEnum::ReturnString>> EntriesManager::getSearchString() {
	EntriesDisplay display(_entries.newEntry, _entries.conflictVector);
	return display.getSearchString(_entries.activeEntries, _entries.searchLabel);
}
vector<vector<CommonEnum::ReturnString>> EntriesManager::getSearchDateString() {
	EntriesDisplay display(_entries.newEntry, _entries.conflictVector);	
	return display.getSearchDateString(_entries.activeEntries, _entries.searchDate.toString(CommonUtils::FORMAT_DATE_HEADER).toStdString());
}

bool EntriesManager::currentDisplayIsEmpty() {
	return _entries.currentDisplayIndex==0;
}

void EntriesManager::updateFile() {
	_file.updateFromVector(getAllEntries());//DEPENDENCY ON FILEMANAGER
	return;
}
void EntriesManager::updateCurrentDisplayIndex() {
	_entries.currentDisplayIndex = _entries.activeEntries.size();
	return;
}
void EntriesManager::updateFoundEntries(const vector<Entry*> &found,const vector<Entry*> &notFound) {
	_entries.activeEntries.clear();
	_entries.activeEntries.insert(_entries.activeEntries.end(), found.begin(), found.end());
	_entries.inactiveEntries.insert(_entries.inactiveEntries.end(), notFound.begin(), notFound.end());
	updateCurrentDisplayIndex();
}

void EntriesManager::clearStack(stack<ENTRIES> &stck) {
	while(!stck.empty()) {
		deleteVector(stck.top().activeEntries);
		deleteVector(stck.top().inactiveEntries);
		stck.pop();
	}
}
//clears the history stack if it has size more than 10
void EntriesManager::clearOverflowUndo() {
	if(_entriesHist.size() > 10) {
		stack<ENTRIES> temp;
		for(int i=0; i<10; i++) {
			temp.push(_entriesHist.top());
			_entriesHist.pop();
		}
		clearStack(_entriesHist);
		while(!temp.empty()) {
			_entriesHist.push(temp.top());
			temp.pop();
		}
	}
}
//updates the txt file and generates a new vector set of pointers
void EntriesManager::generateNewVector() {
	updateFile();
	clearStack(_entriesRedo);
	_entriesHist.push(_entries);
	clearOverflowUndo();//function does nth unless stack of >10
	
	_entries.activeEntries.clear();
	_entries.inactiveEntries.clear();
	
	vector<Entry*> tempVector =_file.getEntries();//generates new vector//DEPENDENCY ON FILEMANAGER
	_entries.activeEntries.assign(tempVector.begin(), tempVector.begin()+_entries.currentDisplayIndex);
	
	tempVector.erase(tempVector.begin(), tempVector.begin()+_entries.currentDisplayIndex);
	
	_entries.inactiveEntries.assign(tempVector.begin(), tempVector.end());
	
	_entries.newEntry=NULL;//remove newEntry
	_entries.conflictVector.clear();//clear conflict vector
	return;
}
void EntriesManager::initEntries() {
	_entries.activeEntries=_file.getEntries();//DEPENDENCY ON FILEMANAGER
	_entries.currentDisplayIndex=_entries.activeEntries.size();
	_entries.currentDisplayFormat=DISPLAY_DEFAULT;
	filterStatus();
}
void EntriesManager::resetSearchAttributes() {
	_entries.searchDate = QDate();//reset search strings
	_entries.searchLabel = "";
	_entries.newEntry=NULL;//remove newEntry
	_entries.conflictVector.clear();//clear conflict vector
	_entries.currentDisplayFormat=DISPLAY_DEFAULT;
}
void EntriesManager::validateIndex(int index) {
	if(index-1 >= (_entries.currentDisplayIndex) || index <=0 ) {//invalid index
		throw BotException(BotException::EXCEPTION_INVALID_INDEX);
	}
}
//reset activentries to all uncompleted entries
void EntriesManager::resetView() {
	_entries.activeEntries=getAllEntries();
	_entries.inactiveEntries.clear();

	filterStatus();

	updateCurrentDisplayIndex();

	resetSearchAttributes();
}
//reset activentries to show all entries including completed
void EntriesManager::showAll() {
	_entries.activeEntries=getAllEntries();
	_entries.inactiveEntries.clear();

	updateCurrentDisplayIndex();

	resetSearchAttributes();
}

void EntriesManager::assignEditAttributes(Entry* &targetEntry, vector<string> entryVector, int index) {
	if(entryVector[0] != STRING_NULL){//corresponds to name
		targetEntry->setName(entryVector[0]);
	}
	//for date and time, assume checking is done in tokeniser
	if(entryVector[1] != STRING_NULL) {//corresponds to starttime
		editStartTime(entryVector[1], targetEntry, index);
	}
	if(entryVector[2] != STRING_NULL) {//corresponds to startdate
		editStartDate(entryVector[2], targetEntry, index);
	}
	if(entryVector[3] != STRING_NULL) {//corresponds to endtime
		targetEntry->setEndTime(QTime::fromString(QString::fromStdString(entryVector[3]), CommonUtils::FORMAT_TIME), CommonEnum::CALLER_ENTRIESMANAGER);
	}
	if(entryVector[4] != STRING_NULL) {//corresponds to enddate
		targetEntry->setEndDate(QDate::fromString(QString::fromStdString(entryVector[4]), CommonUtils::FORMAT_DATE), CommonEnum::CALLER_ENTRIESMANAGER);
	}
}
void EntriesManager::editStartTime(string timeString, Entry* &targetEntry, int index) {
	if(targetEntry->getEntryType() == ENTRY_TYPE_TASK){
		Entry* newEntry = new Event(targetEntry);
		newEntry->setStartDate(targetEntry->getEndDate(), CommonEnum::CALLER_ENTRIESMANAGER);
		newEntry->setStartTime(QTime::fromString(QString::fromStdString(timeString), CommonUtils::FORMAT_TIME), CommonEnum::CALLER_ENTRIESMANAGER);
		delete targetEntry;
		targetEntry = newEntry;
		_entries.activeEntries[index-1] = targetEntry;
	} else {
		targetEntry->setStartTime(QTime::fromString(QString::fromStdString(timeString), CommonUtils::FORMAT_TIME), CommonEnum::CALLER_ENTRIESMANAGER);
	}
}
void EntriesManager::editStartDate(string dateString, Entry* &targetEntry, int index) {
	if(targetEntry->getEntryType() == ENTRY_TYPE_TASK) {
		Entry* newEntry = new Event(targetEntry);
		newEntry->setStartDate((QDate::fromString(QString::fromStdString(dateString), CommonUtils::FORMAT_DATE)), CommonEnum::CALLER_ENTRIESMANAGER);
		delete targetEntry;
		targetEntry = newEntry;
		_entries.activeEntries[index-1] = targetEntry;
	} else {
		targetEntry->setStartDate(QDate::fromString(QString::fromStdString(dateString), CommonUtils::FORMAT_DATE), CommonEnum::CALLER_ENTRIESMANAGER);
	}
}


void EntriesManager::deleteVector(vector<Entry*> &vect) {
	for(int i=0; i< vect.size(); i++) {
		delete vect[i];
		vect[i]=NULL;
	}
	vect.clear();
}

void EntriesManager::filterStatus(bool target) {
	vector<Entry*> found;
	vector<Entry*> notFound;

	EntriesSorter::splitVectorStatus(target, _entries.activeEntries, found, notFound);

	updateFoundEntries(found, notFound);
}
void EntriesManager::filterStatus() {
	filterStatus(false);
}
void EntriesManager::checkUndoStack() {
	if(_entriesHist.size()==0){
		throw BotException(BotException::EXCEPTION_UNDO_INVALID);
	}
}
void EntriesManager::checkRedoStack() {
	if(_entriesRedo.size()==0){
		throw BotException(BotException::EXCEPTION_REDO_INVALID);
	}
}

string EntriesManager::addToEntries(Entry* newEntry) {
	resetView();

	_entries.activeEntries.push_back(newEntry);

	updateCurrentDisplayIndex();
	updateFile();

	_entries.newEntry= newEntry;
	_entries.conflictVector=getConflict(newEntry);

	string messageDisplayed = newEntry->getName();
	return messageDisplayed;
}
string EntriesManager::removeFromEntries(int index) {
	Entry* removedEntry(_entries.activeEntries[index-1]);
	_entries.activeEntries.erase(_entries.activeEntries.begin()+index-1);

	updateCurrentDisplayIndex();
	updateFile();

	string messageDisplayed = removedEntry->getName().c_str();
	return messageDisplayed;
}
string EntriesManager::editEntry(int index, vector<string> entryVector) {
	Entry* targetEntry = _entries.activeEntries[index-1];
	assignEditAttributes(targetEntry, entryVector, index);
	
	updateFile();

	_entries.newEntry = targetEntry;
	_entries.conflictVector = getConflict(_entries.activeEntries[index-1]);

	string messageDisplayed =  _entries.activeEntries[index-1]->getName().c_str();
	return messageDisplayed;
}
string EntriesManager::revertLastState() {
	_entriesRedo.push(_entries);
	_entries = _entriesHist.top();
	_entriesHist.pop();

	updateCurrentDisplayIndex();
	updateFile();

	string messageDisplayed = OUTPUT_MSG_LAST_COMMAND;
	return messageDisplayed;
}
string EntriesManager::revertRedoState() {
	_entriesHist.push(_entries);
	_entries = _entriesRedo.top();
	_entriesRedo.pop();

	updateCurrentDisplayIndex();
	updateFile();

	string messageDisplayed = OUTPUT_MSG_LAST_COMMAND;
	return messageDisplayed;
}
string EntriesManager::clearEntries() {
	deleteVector(_entries.activeEntries);
	deleteVector(_entries.inactiveEntries);

	updateCurrentDisplayIndex();
	updateFile();

	string messageDisplayed = OUTPUT_MSG_ALL;
	return messageDisplayed;
}
string EntriesManager::setEntryDone(int index) {
	_entries.activeEntries[index-1]->setDone();

	updateFile();

	filterStatus();

	string messageDisplayed = _entries.activeEntries[index-1]->getName();
	return messageDisplayed;
}
string EntriesManager::searchEntries(string target, CommonEnum::SEARCH_TYPE searchType) {
	_entries.searchLabel += " " + target;

	vector<Entry*> found;
	vector<Entry*> notFound;

	EntriesSorter::splitVector(target, _entries.activeEntries, found, notFound, searchType);

	updateFoundEntries(found, notFound);

	_entries.currentDisplayFormat=DISPLAY_SEARCH;

	string messageDisplayed = target;
	return messageDisplayed;
}
string EntriesManager::searchEntriesTasks() {
	_entries.searchLabel += " " + ENTRY_TYPE_TASK;

	EntriesSorter::sortByDate(_entries.activeEntries);//sorts all by date

	vector<Entry*> found;
	vector<Entry*> notFound;

	EntriesSorter::splitVectorTask(_entries.activeEntries, found, notFound);

	updateFoundEntries(found, notFound);

	_entries.currentDisplayFormat = DISPLAY_SEARCH;

	string messageDisplayed = ENTRY_TYPE_TASK;
	return messageDisplayed;
}
string EntriesManager::searchEntriesEvents() {
	_entries.searchLabel += " " + ENTRY_TYPE_EVENT;

	EntriesSorter::sortByDate(_entries.activeEntries);

	vector<Entry*> found;
	vector<Entry*> notFound;

	EntriesSorter::splitVectorEvent(_entries.activeEntries, found, notFound);

	updateFoundEntries(found, notFound);

	_entries.currentDisplayFormat = DISPLAY_SEARCH;

	string messageDisplayed = ENTRY_TYPE_EVENT;
	return messageDisplayed;
}
string EntriesManager::searchEntriesDay(QDate target, CommonEnum::SEARCH_TYPE searchType) {
	_entries.searchDate = target;
	resetView();
	vector<Entry*> found;
	vector<Entry*> notFound;

	EntriesSorter::splitVectorDay(target, _entries.activeEntries, found, notFound, searchType);
	
	updateFoundEntries(found, notFound);

	_entries.currentDisplayFormat = DISPLAY_SEARCH_DATE;

	string messageDisplayed = OUTPUT_MSG_ITEMS_IN + target.toString(CommonUtils::FORMAT_DATE).toStdString();
	return messageDisplayed;
}
string EntriesManager::searchEntriesStatus(bool target) {
	showAll();
	filterStatus(target);

	_entries.currentDisplayFormat = DISPLAY_SEARCH;

	string messageDisplayed;

	if(target == false ) {
		messageDisplayed = OUTPUT_MSG_COMPLETE + OUTPUT_MSG_ENTRIES;
	} else {
		 messageDisplayed = OUTPUT_MSG_INCOMPLETE + OUTPUT_MSG_ENTRIES;
	}
	return messageDisplayed;
}